package com.aierkeji.call.cms.util;

import java.beans.PropertyDescriptor;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.support.JdbcUtils;

public class BeanPropertyRowsMapper<T> implements ResultSetExtractor<List<T>> {

	private Class<T> clazz;
	private Map<String, PropertyDescriptor> mappedFields;

	public BeanPropertyRowsMapper(Class<T> clazz) {
		initialize(clazz);
	}

	public Class<T> getClazz() {
		return clazz;
	}

	public void initialize(Class<T> clazz) {
		this.clazz = clazz;
		this.mappedFields = new HashMap<String, PropertyDescriptor>();
		PropertyDescriptor[] pds = org.springframework.beans.BeanUtils.getPropertyDescriptors(clazz);
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null) {
				this.mappedFields.put(pd.getName().toLowerCase(), pd);
				// 将数据库中格式为"xxx_xxx"变成驼峰式"xxxXxx"才需要用到下面的代码
                String underscoredName = underscoreName(pd.getName());
                if (!pd.getName().toLowerCase().equals(underscoredName)) {
                    this.mappedFields.put(underscoredName, pd);
                }
			}
		}
	}

    private String underscoreName(String name) {
        if (!org.springframework.util.StringUtils.hasLength(name)) {
            return "";
        }
        StringBuilder result = new StringBuilder();
        result.append(name.substring(0, 1).toLowerCase());
        for (int i = 1; i < name.length(); i++) {
            String s = name.substring(i, i + 1);
            String slc = s.toLowerCase();
            if (!s.equals(slc)) {
                result.append("_").append(slc);
            }
            else {
                result.append(s);
            }
        }
        return result.toString();
    }

	public List<T> extractData(ResultSet rs) throws SQLException, DataAccessException {
		List<T> list = new ArrayList<T>();
		Class<T> clazz = getClazz();

		try {
			while (rs.next()) {
				T t = org.springframework.beans.BeanUtils.instantiate(clazz);
				BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(t);
				ResultSetMetaData rsmd = rs.getMetaData();
				int columnCount = rsmd.getColumnCount();
				for (int i = 1; i <= columnCount; i++) {
					String column = StringUtils.capitalize(JdbcUtils.lookupColumnName(rsmd, i));
					PropertyDescriptor pd = this.mappedFields.get(column.replaceAll(" ", "").toLowerCase());
					if (pd != null) {
						Object value = JdbcUtils.getResultSetValue(rs, i, pd.getPropertyType());
						bw.setPropertyValue(pd.getName(), value);
					}
				}
				list.add(t);
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		}
		return list;
	}
}